/*
 * RemoteTurnSubStateController.cpp
 *
 *  Created on: Dec 30, 2011
 *      Author: rudi
 */
#include <vector>
#include <wx/filename.h>
#include <wx/socket.h>
#include "RemoteTurnSubStateController.h"
#include "LocalTurnSubStateController.h"
#include "GameStartedGameStateController.h"
#include "SmartPointer.h"
#include "MainPanel.h"
#include "MainFrame.h"
#include "Vehicle.h"
#include "App.h"
#include "WxUtils.h"
#include "Configuration.h"

RemoteTurnSubStateController::RemoteTurnSubStateController(): mLevel(NULL),
															  mOriginalLevel(NULL),
															  mDynamicDrawController(NULL),
															  mIsDataReceived(false)
{
	wxChar pathSeparator = wxFileName::GetPathSeparator();
	wxString level = wxGetApp().getActualLevel();
	wxString imagePath = wxGetCwd() + pathSeparator + wxGetApp().getConfiguration()->getLevels()->getPath() + pathSeparator + level + pathSeparator + level + wxT(".bmp");
	int dotSize = wxGetApp().getConfiguration()->getDotSize();
	wxPoint localPosition = wxGetApp().getConfiguration()->getLevels()->getLevel(level)->getVehicleB()->getPosition();
	wxPoint remotePosition = wxGetApp().getConfiguration()->getLevels()->getLevel(level)->getVehicleA()->getPosition();
	SmartPointer<Vehicle> localVehicle = NULL;
	SmartPointer<Vehicle> remoteVehicle = NULL;
	SmartPointer<std::vector<wxPoint> > localVehicleArrows = NULL;
	SmartPointer<std::vector<wxPoint> > remoteVehicleArrows = NULL;

	// Start the game itself
	mLevel = new wxBitmap(imagePath, wxBITMAP_TYPE_BMP);
	mOriginalLevel = new wxImage(mLevel->ConvertToImage());
	// Create the vehicles and put them on the starting point
	localVehicle = new Vehicle(localPosition, mLevel, dotSize);
	remoteVehicle = new Vehicle(remotePosition, mLevel, dotSize);
	// At the beginning the lists of points are empty
	localVehicleArrows = new std::vector<wxPoint>();
	remoteVehicleArrows = new std::vector<wxPoint>();
	mDynamicDrawController = new DynamicDrawController(mLevel, mOriginalLevel, remoteVehicle, localVehicle, remoteVehicleArrows, localVehicleArrows, WxUtils::INVALID_POINT);
	wxGetApp().getMainFrame()->GetStatusBar()->SetStatusText(wxT("Opponent's turn"));
	// Load the new level
	wxGetApp().getMainFrame()->getMainPanel()->Refresh();
}

RemoteTurnSubStateController::RemoteTurnSubStateController(SmartPointer<wxBitmap> level,
														   SmartPointer<wxImage> originalLevel,
														   SmartPointer<DynamicDrawController> dynamicDrawController): mLevel(level),
																													   mOriginalLevel(originalLevel),
																													   mDynamicDrawController(dynamicDrawController),
																													   mIsDataReceived(false)
{
	wxGetApp().getMainFrame()->GetStatusBar()->SetStatusText(wxT("Opponent's turn"));
}

/*virtual*/
RemoteTurnSubStateController::~RemoteTurnSubStateController()
{
	// Nothing to do yet
}

//
// Methods inherited from Controller
//

void RemoteTurnSubStateController::handleMouseDown(const wxPoint& position)
{
	// Do not handle the user's motions, only show the movements from the remote side
	if(true == mIsDataReceived)
		mDynamicDrawController->handleMouseDown(position);
}

void RemoteTurnSubStateController::handleMouseUp(const wxPoint& position)
{
	// Do not handle the user's motions, only show the movements from the remote side
	if(true == mIsDataReceived)
	{
		mDynamicDrawController->handleMouseUp(position);
		mGameStartedController->changeSubState(this->getNextSubStateController());
	}
}

bool RemoteTurnSubStateController::handleMouseMotion(const wxPoint& position)
{
	// Do not handle the user's motions, only show the movements from the remote side
	if(true == mIsDataReceived)
		return mDynamicDrawController->handleMouseMotion(position);

	return false;
}

const wxBitmap& RemoteTurnSubStateController::getBitmapToPaint() const
{
	return mDynamicDrawController->getBitmapToPaint();
}

wxBitmap& RemoteTurnSubStateController::getBitmapToDraw()
{
	return mDynamicDrawController->getBitmapToDraw();
}

//
// Methods inherited from GameStateController
//

void RemoteTurnSubStateController::handleSocketConnection(wxSocketEvent&)
{
	wxASSERT_MSG(false, wxT("RemoteTurnSubStateController::handleSocketConnection called. Could not happen!"));
}

void RemoteTurnSubStateController::handleSocketLost(wxSocketEvent&)
{
	wxASSERT_MSG(false, wxT("RemoteTurnSubStateController::handleSocketLost called. Could not happen!"));
}

void RemoteTurnSubStateController::handleSocketInput(wxSocketEvent& socketEvent)
{
	SmartPointer<NetworkEventData> data = NULL;
	wxSocketBase* socket = wxGetApp().getClientSocket();

	// If this event is not happened on our socket, there is nothing to do.
	if(socketEvent.GetSocket() != socket)
		return;
	data = new NetworkEventData();
	// Check if an error occurred or not
	if(false == data->read(socket))
		return;
	// While the received data is under processing this variable should be set to true, to make a difference
	// between the events from the user or from the other side
	mIsDataReceived = true;
	switch(data->getDataType())
	{
		case NetworkEventData::MOUSE_DOWN:
			this->handleMouseDown(wxPoint(data->getX(), data->getY()));
			break;
		case NetworkEventData::MOUSE_UP:
			this->handleMouseUp(wxPoint(data->getX(), data->getY()));
			break;
		case NetworkEventData::MOUSE_MOTION:
			this->handleMouseMotion(wxPoint(data->getX(), data->getY()));
			break;
		default:
			wxASSERT_MSG(false, wxT("RemoteTurnSubStateController::handleSocketinput called with invalid data type!"));
			break;
	}
	// Set back the variable after the processing is done
	mIsDataReceived = false;
}

void RemoteTurnSubStateController::handleSocketOutput(wxSocketEvent&)
{
	wxASSERT_MSG(false, wxT("RemoteTurnSubStateController::handleSocketOutput called. Could not happen!"));
}

//
// Methods inherited from GameStartedSubStateController
//

GameStartedSubStateController::SubstateId RemoteTurnSubStateController::getSubstateId()
{
	return GameStartedSubStateController::REMOTE_TURN;
}

GameStartedSubStateController* RemoteTurnSubStateController::getNextSubStateController()
{
	// Create a new draw controller from the current one
	SmartPointer<DynamicDrawController> dynamicDrawController = new DynamicDrawController(mLevel, mOriginalLevel,
																						  mDynamicDrawController->getRemoteVehicle(),
																						  mDynamicDrawController->getActualVehicle(),
																						  mDynamicDrawController->getRemoteVehicleArrows(),
																						  mDynamicDrawController->getActualVehicleArrows(),
																						  mDynamicDrawController->getFirstStep());
	return new LocalTurnSubStateController(mLevel, mOriginalLevel, dynamicDrawController);
}
